import { computed, onMounted, ref } from 'vue'
import { useIntervalFn } from '@vueuse/core'
import veeSchema from '@/utils/vee-validate-schema'
import API from '@/api/user'
import Message from '@/components/library/Message'

/**
 * 发送短信的逻辑 (包含校验)
 * @param formRef       表单对象
 * @param form          表单数据对象
 * @param sendCodeAPI   发送短信的API  默认值 API.userMobileLoginMsg
 */
export default function codeUtil(form, formRef, sendCodeAPI = API.userMobileLoginMsg) {
  const time = ref(0)
  // 使用useInterValFn 的好处, 可以把定时器的逻辑抽出来
  // useInterValFn(回调函数, 执行间隔, 是否立即开启)
  const {
    resume,   // 开始
    pause     // 暂停
  } = useIntervalFn(() => {
    time.value--
    if (time.value <= 0) {
      pause()
    }
  }, 1000, false)

  // 组件销毁时, 将定时器清除
  onMounted(() => {
    pause()
  })

  const codeStr = computed(() => {
    return time.value === 0 ? '发送验证码' : `${time.value}秒后发送`
  })

  // 发送短信
  // 1.发送验证码
  // 1.1.绑定发送验证码按钮点击事件
  // 1.2.校验手机号, 如果成功才发送短信(定义API), 请求成功开启60s的倒计时, 不能再次点击
  // 1.3.如果失败, 失败的校验样式显示出来
  const sendCode = async () => {
    const valid = veeSchema.mobile(form.mobile)
    // valid 要么是 true, 要么是错误提示字符串, 所以不能使用 if(valid)省略判断
    if (valid === true) {
      // 通过
      // 没有倒计时才可以发送
      if (time.value === 0) {
        // todo 这个地方要重构了, QQ绑定发送的验证API 和 登录的发送短信的API不一样, 使用回调函数形式吗?
        //      由于这些不同发送短信方法参数都是一个手机号, 所以这里没必要继续优化
        //      解决参数不一致问题, 方法上在定义一个形参数组或对象, 然后调用方法时使用扩展运算符将数组转为参数序列
        try {
          await sendCodeAPI(form.mobile)
          Message({
            type: 'success',
            text: '发送成功'
          })
          time.value = 60
          resume()
        } catch (err) {
          // 发送短信也会出现400的异常!!!, 所有需要使用catch捕获到
          // 失败消息提示
          if (err.response.data) {
            Message({
              type: 'error',
              text: err.response.data.message || '获取验证码失败'
            })
          }
        }
      }
    } else {
      // 失败, 使用vee的错误函数显示错误信息 setFieldError(字段, 错误信息) 设置字段错误
      formRef.value.setFieldError('mobile', valid)
    }
  }

  return {
    sendCode,
    codeStr
  }
}


